package com.dingreading.cloud.soms.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.*;
import com.dingreading.cloud.soms.dto.*;
import com.dingreading.cloud.soms.entity.Members;
import com.dingreading.cloud.soms.entity.Staff;
import com.dingreading.cloud.soms.entity.table.MembersTableDef;
import com.dingreading.cloud.soms.mapper.MembersMapper;
import com.dingreading.cloud.soms.service.MembersService;
import com.dingreading.cloud.soms.service.StaffService;
import com.dingreading.cloud.soms.util.ScheduleUtil;
import com.google.common.collect.Lists;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 服务层实现。
 *
 * @author Administrator
 * @since 2023-11-22
 */
@Service
public class MembersServiceImpl extends BaseServiceImpl<MembersMapper, Members, MembersTableDef> implements MembersService {

    @Resource
    private StaffService staffService;

    @Override
    protected MembersTableDef getTable() {
        return MembersTableDef.members;
    }

    @Resource
    private MembersMapper membersMapper;


    @Override
    public Members getByUid(String storeUid, String uid) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (null != storeUid)
            condition.and(table.storeUid.eq(storeUid));
        condition.and(table.uid.eq(uid));
        return getMapper().selectOneByCondition(condition);
    }

    @Override
    public List<Members> getByUids(List<String> uid) {
        return getMapper().selectListByCondition(table.uid.in(uid));
    }

    @Override
    public List<Members> getByFullName(String fullName) {
        QueryWrapper wrapper = QueryWrapper.create()
                .where(table.fullName.eq(fullName))
                .orderBy(table.id.desc());
        return getMapper().selectListByQuery(wrapper);
    }

    @Override
    public List<Members> getByMemberNameAndFullNameAndMob(String storeUid, String keyword) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.enabled.eq(1))
                .and(table.validStatus.eq(1))
                .and(table.memberName.like(keyword)
                             .or(table.fullName.like(keyword))
                             .or(table.nickName.like(keyword))
                             .or(table.mob.like(keyword))
                );
        return getMapper().selectListByCondition(condition);
    }

    @Override
    public List<Members> getByStoreUidAndKeyword(String corpUid, String storeUid, String keyword, Integer enabled) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.corpUid.eq(corpUid))
                .and(table.storeUid.eq(storeUid))
                .and(table.validStatus.eq(1));
        if (null != enabled)
            condition.and(table.enabled.eq(enabled));
        if (StringUtils.isNotBlank(keyword))
            condition.and(table.fullName.like(keyword)
                                  .or(table.memberName.like(keyword))
                                  .or(table.nickName.like(keyword))
                                  .or(table.mob.like(keyword))
            );

        QueryWrapper wrapper = QueryWrapper.create()
                .select(table.fullName, table.memberName, table.nickName, table.uid, table.mob,
                        table.enabled, table.status)
                .from(table)
                .where(condition)
                .orderBy(table.id.desc(), table.enabled.desc());

        return getMapper().selectListByQuery(wrapper);
    }

    @Override
    public Members getMemberInfo(String corpUid, String uid) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.corpUid.eq(corpUid))
                .and(table.uid.eq(uid));

        QueryWrapper wrapper = QueryWrapper.create()
                .select(table.storeUid, table.storeName, table.fullName, table.memberName, table.mob, table.wxName,
                        table.enabled, table.uid, table.sex, table.grade, table.dateOfBirth,
                        table.customSource, table.customSourceRemark, table.channelUid, table.channelName, table.refererMemberName, table.refererMemberUid,
                        table.refererStaffUid, table.refererStaffName, table.status, table.schoolName, table.houseName, table.validStatus)
                .where(condition);
        return getMapper().selectOneByQuery(wrapper);
    }

    @Override
    public boolean updateEnabled(String storeUid, String uid, Integer enabled, String staffUid, String staffName, Date followTime) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.uid.eq(uid));
        return UpdateChain.of(Members.class)
                .set(table.enabled, enabled)
                .set(table.followTime, followTime)
                .where(condition)
                .update();
    }

    @Override
    public boolean allotFollowStaff(String storeUid, List<String> memberUid, String staffUid, String staffName) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.uid.in(memberUid));
        return UpdateChain.of(Members.class)
                .set(table.followStaffUid, staffUid)
                .set(table.followStaffName, staffName)
                .where(condition)
                .update();
    }

    @Override
    public boolean giveUp(String storeUid, String memberUid, String staffUid) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.uid.in(memberUid));
        if (null != staffUid)
            condition.and(table.followStaffUid.in(staffUid));
        return UpdateChain.of(Members.class)
                .set(table.followStaffUid, null)
                .set(table.followStaffName, null)
                .where(condition)
                .update();
    }

    @Override
    public PageDto<AddMemberDto> getByServiceMembers(
            PageUtil pageUtil, String corpUid, String storeUid, String fullName, Integer grade, String readStaffUid) {
        //设置其他参数
        Map<String, Object> otherParams = new HashMap<>();
        otherParams.put("corpUid", corpUid);
        otherParams.put("storeUid", storeUid);
        otherParams.put("fullName", fullName);
        otherParams.put("grade", grade);
        otherParams.put("readStaffUid", readStaffUid);

        Page<AddMemberDto> page = getMapper().xmlPaginate("getByServiceMembers", Page.of(pageUtil.getPage(), pageUtil.getRows()), otherParams);

        long count = page.getTotalRow();
        List<AddMemberDto> list = page.getRecords();

        if (CollectionUtils.isNotEmpty(list)) {
            for (AddMemberDto dto : list) {
                dto.setLeftLessonCnt(0);
                dto.setProductName("");
            }
        }

        PageDto<AddMemberDto> data = new PageDto<>();
        data.setTotal(count);
        data.setList(list);
        return data;
    }

    @Override
    public PageDto<AddMemberDto> getAuditionMembers(PageUtil pageUtil, String corpUid, String storeUid, String keyword) {
        //设置其他参数
        Map<String, Object> otherParams = new HashMap<>();
        otherParams.put("corpUid", corpUid);
        otherParams.put("storeUid", storeUid);
        otherParams.put("keyword", keyword);

        Page<AddMemberDto> page = getMapper().xmlPaginate("getAuditionMembers", Page.of(pageUtil.getPage(), pageUtil.getRows()), otherParams);

        long count = page.getTotalRow();
        List<AddMemberDto> list = page.getRecords();

        if (CollectionUtils.isNotEmpty(list)) {
            for (AddMemberDto dto : list) {
                dto.setLeftLessonCnt(0);
                dto.setProductName("");
            }
        }

        PageDto<AddMemberDto> data = new PageDto<>();
        data.setTotal(count);
        data.setList(list);
        return data;
    }

    @Override
    public PageDto<AddMemberDto> serviceMemberList(
            PageUtil pageUtil, String corpUid, String storeUid, String fullName, Integer grade,
            String projectUid, String readStaffUid
    ) {
        //设置其他参数
        Map<String, Object> otherParams = new HashMap<>();
        otherParams.put("corpUid", corpUid);
        otherParams.put("storeUid", storeUid);
        otherParams.put("fullName", fullName);
        otherParams.put("grade", grade);
        otherParams.put("projectUid", projectUid);
        otherParams.put("readStaffUid", readStaffUid);
        // 体验课服务uid
        otherParams.put("tyProjectUid", ScheduleUtil.TIYAN_UID);

        Page<AddMemberDto> page = getMapper().xmlPaginate("serviceMemberList", Page.of(pageUtil.getPage(), pageUtil.getRows()), otherParams);

        long count = page.getTotalRow();
        List<AddMemberDto> list = page.getRecords();

        PageDto<AddMemberDto> data = new PageDto<>();
        data.setTotal(count);
        data.setList(list);
        return data;
    }

    @Override
    public List<JSONObject> getCorpMembers(String corpUid, String storeUid, String keyword) {
        List<Members> list = membersMapper.getCorpMembers(corpUid, storeUid, keyword);
        List<JSONObject> array = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)) {
            for (Members members : list) {
                String uid = members.getUid();
                String storeName = members.getStoreName();
                String memberName = members.getMemberName();
                String fullName = members.getFullName();
                String nickName = members.getNickName();
                String mob = members.getMob();

                JSONObject object = new JSONObject();
                object.put("uid", uid);
                object.put("storeName", storeName);
                object.put("memberName", memberName);
                object.put("fullName", fullName);
                object.put("nickName", nickName);
                object.put("mob", mob);
                array.add(object);
            }
        }
        return array;
    }

    @Override
    public void updateLastFollowInfo(String storeUid, String memberUid, String followUid, Date followTime) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.uid.eq(memberUid));
        UpdateChain.of(Members.class)
                .set(table.lastFollowUid, followUid)
                .set(table.followTime, followTime)
                .where(condition)
                .update();
    }

    @Override
    public void updateFollowTimes(String storeUid, List<String> memberUids, Date time) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.uid.in(memberUids));
        UpdateChain.of(Members.class).set(table.followTime, time).where(condition).update();
    }

    @Override
    public Members haveCorpUidAndMobAndFullName(String corpUid, String mob, String fullName, String uid) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.corpUid.eq(corpUid))
                .and(table.mob.eq(mob))
                .and(table.fullName.eq(fullName));
        if (StringUtils.isNotBlank(uid))
            condition.and(table.uid.ne(uid));
        return getMapper().selectOneByCondition(condition);
    }

    @Override
    public Members haveCorpUidAndWxNameAndFullName(String corpUid, String wxName, String fullName, String uid) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.corpUid.eq(corpUid))
                .and(table.wxName.eq(wxName))
                .and(table.fullName.eq(fullName));
        if (StringUtils.isNotBlank(uid))
            condition.and(table.uid.ne(uid));
        return getMapper().selectOneByCondition(condition);
    }

    @Override
    public Members haveCorpUidAndStoreUidAndMobAndFullName(String corpUid, String storeUid, String mob, String fullName) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.corpUid.eq(corpUid))
                .and(table.storeUid.eq(storeUid))
                .and(table.mob.eq(mob))
                .and(table.fullName.eq(fullName));
        return getMapper().selectOneByCondition(condition);
    }


    @Override
    public PageDto<MembersDto> getMemberListByType(
            PageUtil pageUtil, boolean managerOrAdvisor, String storeUid, String keyword, Integer enabled, String beginDate,
            String endDate, String followStaffUid, Integer grade, Integer memberType, String customSource, String channelUid
    ) {
        //设置其他参数
        Map<String, Object> otherParams = new HashMap<>();
        otherParams.put("storeUid", storeUid);
        otherParams.put("keyword", keyword);
        otherParams.put("enabled", enabled);
        otherParams.put("beginDate", beginDate);
        otherParams.put("followStaffUid", followStaffUid);
        otherParams.put("grade", grade);
        otherParams.put("memberType", memberType);
        otherParams.put("customSource", customSource);
        otherParams.put("channelUid", channelUid);
        otherParams.put("orderTypes", Lists.newArrayList(EnumType.OrderType.EXP.getType(), EnumType.OrderType.GIFT.getType()));
        otherParams.put("time", DateUtil.getNowDateStr());

        Page<MembersDto> page = getMapper().xmlPaginate("getMemberListByType", Page.of(pageUtil.getPage(), pageUtil.getRows()), otherParams);

        long count = page.getTotalRow();
        List<MembersDto> list = page.getRecords();

        if (CollectionUtils.isNotEmpty(list)) {
            for (MembersDto dto : list) {
                // 不是店长或顾问
                if (!managerOrAdvisor) {
                    // 隐藏手机号码
                    String mob = dto.getMob();
                    if (StringUtils.isNotBlank(mob) && mob.length() == 11) {
                        dto.setMob(RegularUtil.hidePhone(mob));
                    }
                    // 隐藏微信号
                    String wxName = dto.getWxName();
                    if (StringUtils.isNotBlank(wxName)) {
                        dto.setWxName(RegularUtil.hideWxName(wxName, 2, 2));
                    }
                }

                dto.setServiceNum(dto.getCnt());
            }
        }

        PageDto<MembersDto> pageDto = new PageDto<>();
        pageDto.setTotal(count);
        pageDto.setList(list);

        return pageDto;
    }

    @Override
    public boolean haveChannelUid(String storeUid, String channelUid) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.channelUid.eq(channelUid));

        return exists(condition);
    }

    @Override
    public boolean updateValidStatus(String storeUid, String uid, int validStatus, String staffUid, String staffName) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.uid.eq(uid));
        return UpdateChain.of(Members.class)
                .set(table.validStatus, validStatus)
                .set(table.lastStaffUid, NepUtil.nullToZero(staffUid))
                .set(table.lastStaffName, NepUtil.nullToZero(staffName))
                .where(condition).update();
    }

    @Override
    public int dropClueMember(String storeUid, String uid) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.uid.eq(uid))
                .and(table.validStatus.ne(1));
        return getMapper().deleteByCondition(condition);
    }

    @Override
    public boolean updateStoreInfo(String storeUid, String memberUid, Long storeId, String toStoreUid, String toStoreName) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.uid.eq(memberUid))
                .and(table.validStatus.eq(1));
        return UpdateChain.of(Members.class)
                .set(table.storeId, storeId)
                .set(table.storeUid, toStoreUid)
                .set(table.storeName, toStoreName)
                .where(condition)
                .update();
    }

    @Override
    public Members getByUid(String uid) {
        QueryWrapper wrapper = QueryWrapper.create()
                .select(table.uid, table.fullName, table.memberName, table.storeUid, table.grade, table.corpUid)
                .from(table)
                .where(table.uid.eq(uid));
        return getMapper().selectOneByQuery(wrapper);
    }

    @Override
    public List<MemberBorrowDto> borrowMemberList(String corpUid, String storeUid, String keyword) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.eq(storeUid))
                .and(table.validStatus.eq(1));
        if (StringUtils.isNotBlank(keyword))
            condition.and(table.fullName.like(keyword)
                                  .or(table.memberName.like(keyword))
                                  .or(table.nickName.like(keyword))
                                  .or(table.mob.like(keyword))
            );

        QueryWrapper wrapper = QueryWrapper.create()
                .from(table)
                .where(condition)
                .limit(0, 10)
                .orderBy(table.id.desc(), table.enabled.desc());

        return getMapper().selectListWithRelationsByQueryAs(wrapper, MemberBorrowDto.class);
    }

    @Override
    public List<MemberBorrowDto> borrowMemberList(List<String> storeUidList, String keyword) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(table.storeUid.in(storeUidList))
                .and(table.validStatus.eq(1));
        if (StringUtils.isNotBlank(keyword))
            condition.and(table.fullName.like(keyword)
                                  .or(table.memberName.like(keyword))
                                  .or(table.nickName.like(keyword))
                                  .or(table.mob.like(keyword))
            );

        QueryWrapper wrapper = QueryWrapper.create()
                .from(table)
                .where(condition)
                .limit(0, 10)
                .orderBy(table.id.desc(), table.enabled.desc());

        return getMapper().selectListWithRelationsByQueryAs(wrapper, MemberBorrowDto.class);
    }

    @Override
    public MaxFullNameDto maxFullName(String fullName) {
        return membersMapper.maxFullName(fullName);
    }

    @Override
    public List<Members> listByPhoneList(List<String> searchPhoneList) {
        return getMapper().selectListByCondition(table.mob.in(searchPhoneList));
    }

    @Override
    public Page<MemberClueDto> getMemberClueList(
            PageUtil pageUtil, String storeUid, String keyword, Integer enabled, String beginDate, String endDate,
            String followStaffUid, Integer grade, String customSource, String channelUid, String refererStaffUid,
            String addStaffUid, Integer validStatus
    ) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (StringUtils.isNotBlank(storeUid))
            condition.and(table.storeUid.eq(storeUid));
        condition.and(table.source.in(EnumType.Source.XCX.getName(), EnumType.Source.MARKET.getName()));
        if (null != grade)
            condition.and(table.grade.eq(grade));
        if (null != enabled)
            condition.and(table.enabled.eq(enabled));
        if (StringUtils.isNotBlank(followStaffUid))
            condition.and(table.followStaffUid.eq(followStaffUid));
        if (StringUtils.isNotBlank(customSource))
            condition.and(table.customSource.eq(customSource));
        if (StringUtils.isNotBlank(channelUid))
            condition.and(table.channelUid.eq(channelUid));
        if (StringUtils.isNotBlank(refererStaffUid))
            condition.and(table.refererStaffUid.eq(refererStaffUid));
        if (StringUtils.isNotBlank(addStaffUid))
            condition.and(table.addStaffUid.eq(addStaffUid));
        if (null != validStatus) {
            condition.and(table.validStatus.eq(validStatus));
        } else {
            condition.and(table.validStatus.in(0, 1, -1));
        }
        if (StringUtils.isNotBlank(keyword))
            condition.and(table.fullName.like(keyword)
                                  .or(table.memberName.like(keyword))
                                  .or(table.nickName.like(keyword))
                                  .or(table.mob.like(keyword)));
        if (StringUtils.isNotBlank(beginDate) && StringUtils.isNotBlank(endDate)) {
            condition.and(table.addTime.between(QueryFiledUtil.appendMin00(beginDate), QueryFiledUtil.appendMin24(endDate)));
        }

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.id.desc());

        return getMapper().paginateWithRelationsAs(Page.of(pageUtil.getPage(), pageUtil.getRows()), wrapper, MemberClueDto.class);
    }

    @Override
    public List<MemberUidSourceDto> listByAddTimeBetween(String storeUid, String beginDate, String endDate) {
        QueryCondition condition = table.storeUid.eq(storeUid)
                .and(table.addTime.between(QueryFiledUtil.appendMin00(beginDate), QueryFiledUtil.appendMin24(endDate)))
                .and(table.validStatus.eq(1))
                .and(table.enabled.eq(1));
        QueryWrapper wrapper = QueryWrapper.create()
                .select(table.uid, table.customSource, table.validStatus)
                .from(table)
                .where(condition);

        return getMapper().selectListByQueryAs(wrapper, MemberUidSourceDto.class);
    }


    @Override
    public List<Members> findByMobAndFullName(String storeUid, String mob, String fullName) {
        return membersMapper.findByMobAndFullName(storeUid, mob, fullName);
    }

    @Override
    public void updateDatabaseType(String uid, String mstUid, int databaseType) {
        UpdateChain.of(Members.class)
                .set(table.validStatus, 1)
                .set(table.databaseType, databaseType)
                .set(table.mstUid, mstUid)
                .where(table.uid.in(uid))
                .update();
    }

    @Override
    public List<Members> mstMemberList(String storeUid) {
        QueryCondition condition = table.storeUid.eq(storeUid)
                .and(table.databaseType.in(2, 3));
        return getMapper().selectListByCondition(condition);
    }

    @Override
    public List<Members> getByPhone(String phone) {
        QueryCondition condition = QueryCondition.createEmpty()
                .and(table.mob.eq(phone))
                .and(table.enabled.eq(1));
        return getMapper().selectListByCondition(condition);
    }

    @Override
    public List<Members> listByStoreUidAndMstUid(String storeUid, List<String> studentUidList) {
        return getMapper().selectListByCondition(table.storeUid.eq(storeUid).and(table.mstUid.in(studentUidList)));
    }

    @Override
    public R<Object> setReferer(
            String corpUid, String storeUid, String storeName,
            String staffUid, String staffName, List<String> uids, String refererStaffUid
    ) {
        if (CollectionUtils.isEmpty(uids))
            return R.fail("请选择会员！");
        if (StringUtils.isBlank(refererStaffUid))
            return R.fail("请选择市场人员！");
        if (StringUtils.isBlank(corpUid) || StringUtils.isBlank(storeUid) || StringUtils.isBlank(staffUid))
            return R.fail("员工信息缺少！");

        QueryCondition condition = QueryCondition.createEmpty()
                .and(table.uid.in(uids));
        List<Members> members = getMapper().selectListByCondition(condition);
        if (CollectionUtils.isEmpty(members)) {
            return R.fail("会员不存在！");
        }

        String staffPubPhone = "";
        String staffPriPhone = "";
        String staffNickName = "";
        String staffFullName = "";
        if (StringUtils.isNotBlank(refererStaffUid)) {
            Staff staff = staffService.getByUid(refererStaffUid);
            if (null == staff) return R.fail("市场人员获取失败");
            staffFullName = staff.getFullName();
            if (StringUtils.isBlank(staffFullName))
                return R.fail("请先完善市场人员的全名");
            staffPriPhone = staff.getPriPhone();
            staffPubPhone = staff.getPubPhone();
            staffNickName = staff.getNickName();
        }

        // 判断会员是否已存在市场人员refererStaffUid, 30天内的会员
        List<String> memberNamesForReferer = new ArrayList<>();
        List<String> memberNamesForTime = new ArrayList<>();
        for (Members member : members) {
            if (StringUtils.isNotBlank(member.getRefererStaffUid()))
                memberNamesForReferer.add(member.getMemberName());
            if (TimeUtil.moreThanDay(member.getAddTime(), 30))
                memberNamesForTime.add(member.getMemberName());

            member.setRefererStaffUid(refererStaffUid);
            member.setRefererStaffName(staffNickName);
            member.setRefererStaffFullName(staffFullName);
            member.setRefererStaffPriPhone(staffPriPhone);
            member.setRefererStaffPubPhone(staffPubPhone);
            member.setLastStaffUid(staffUid);
            member.setLastStaffName(staffName);
        }
        if (CollectionUtils.isNotEmpty(memberNamesForReferer))
            return R.fail("会员已存在市场人员:" + memberNamesForReferer);
        if (CollectionUtils.isNotEmpty(memberNamesForTime))
            return R.fail("会员已超过30天:" + memberNamesForTime);

        boolean b = updateBatch(members);
        return b ? R.ok() : R.fail("批量设置市场人员失败");
    }

}
